package com.photologics.main;

import java.util.StringTokenizer;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.util.Log;

public class DbAdapter {

	public static final String KEY_NAME = "_id";
	public static final String KEY_COMPLETENESS = "completeness";
	public static final String KEY_VALUE = "value";
	public static final String KEY_STATE = "state";
	public static final String KEY_TIME = "time";

	public static final int FIND_BY_NAME = 0;
	public static final int FIND_BY_COMPLETENESS = 1;
	public static final int FIND_BY_VALUE = 2;
	public static final int FIND_BY_STATE = 3;
	public static final int FIND_BY_TIME = 4;

	private static final String TAG = "DbAdapter";
	private DatabaseHelper mDbHelper;
	private SQLiteDatabase mDb; // �����ͺ��̽��� ����

	private static final String DATABASE_CREATE = "create table logicdata(_id text primary key not null,"
			+ "completeness text not null, value text not null, state text not null, time integer not null);";

	private static final String DATABASE_NAME = "logicdb.db";
	private static final String DATABASE_TABLE = "logicdata";

	public static final String KEY_COIN = "coin";
	public static final String KEY_HORIZON = "horizon";
	public static final String KEY_VERTICAL = "vertical";
	public static final String KEY_SQUAR = "squar";
	public static final String KEY_SHOW = "show";
	public static final String KEY_REMOVEX = "removex";

	public static final int FIND_BY_COIN = 0;
	public static final int FIND_BY_HORIZON = 1;
	public static final int FIND_BY_VERTICAL = 2;
	public static final int FIND_BY_SQUAR = 3;
	public static final int FIND_BY_SHOW = 4;
	public static final int FIND_BY_REMOVEX = 5;

	private static final String DATABASE_CREATE2 = "create table logicitem(coin integer primary key not null,"
			+ "horizon integer not null, vertical integer not null, squar integer not null, show integer not null, removex integer not null);";

	private static final String DATABASE_TABLE2 = "logicitem";

	private static final int DATABASE_VERSION = 3;

	private final Context mCtx; // ?

	private class DatabaseHelper extends SQLiteOpenHelper {

		public DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
			// TODO Auto-generated constructor stub
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL(DATABASE_CREATE);
			db.execSQL(DATABASE_CREATE2);
			
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			if (oldVersion == 1) {
				Log.w(TAG, "Upgrading db from version" + oldVersion + " to"
						+ newVersion + ", add time column");
				db.execSQL("ALTER TABLE logicdata ADD COLUMN time INTEGER");
				db.execSQL(DATABASE_CREATE2);

			}
			if (oldVersion == 2){
				db.execSQL(DATABASE_CREATE2);
			
			}
		}

	}

	public DbAdapter(Context ctx) {
		this.mCtx = ctx;
	}

	public DbAdapter open() throws SQLException {
		mDbHelper = new DatabaseHelper(mCtx);
		mDb = mDbHelper.getWritableDatabase();
		return this;
	}

	public void close() {
		mDbHelper.close();
	}

	// ���ڵ� ��
	public long createLogic(String name, byte[][] value) {

		int length = value.length;

		ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_NAME, name);

		switch (length) {
		case 50:
			initialValues.put(KEY_COMPLETENESS, "0,0,0,0");
			break;
		case 100:
			initialValues.put(KEY_COMPLETENESS,
					"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
			break;
		case 150:
			initialValues
					.put(KEY_COMPLETENESS,
							"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
			break;
		}

		String valueString = arrayToString(value);
		initialValues.put(KEY_VALUE, valueString);

		byte[][] byteState = new byte[length][length];
		String stateStrings = arrayToString(byteState);
		initialValues.put(KEY_STATE, stateStrings);

		long time = 0;
		initialValues.put(KEY_TIME, time);

		return mDb.insert(DATABASE_TABLE, null, initialValues);
	}

	public long createLogic(String name, String value) {

		String valueTemp = stretchString(value);

		int length = valueTemp.length();

		ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_NAME, name);

		switch (length) {
		case 2500:
			initialValues.put(KEY_COMPLETENESS, "0,0,0,0");
			break;
		case 10000:
			initialValues.put(KEY_COMPLETENESS,
					"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
			break;
		case 22500:
			initialValues
					.put(KEY_COMPLETENESS,
							"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
			break;
		}

		initialValues.put(KEY_VALUE, valueTemp);
		int count = (int) Math.sqrt(length);

		byte[][] byteState = new byte[count][count];
		String stateStrings = arrayToString(byteState);
		initialValues.put(KEY_STATE, stateStrings);

		long time = 0;
		initialValues.put(KEY_TIME, time);

		return mDb.insert(DATABASE_TABLE, null, initialValues);
	}

	// ���ڵ� ����
	public boolean deleteLogic(String name) {
		return mDb.delete(DATABASE_TABLE, KEY_NAME + "=" + "'" + name + "'",
				null) > 0;
	}

	// ��� ���ڵ� ��ȯ
	public Cursor fetchAllLogic() {
		return mDb.query(DATABASE_TABLE, new String[] { KEY_NAME,
				KEY_COMPLETENESS, KEY_VALUE, KEY_STATE, KEY_TIME }, null, null,
				null, null, null);

	}
	
	// Ư�� ���ڵ� ��ȯ
	public Cursor fetchLogic(String name) throws SQLException {
		Cursor mCursor = mDb.query(DATABASE_TABLE, new String[] { KEY_NAME,
				KEY_COMPLETENESS, KEY_VALUE, KEY_STATE, KEY_TIME }, KEY_NAME
				+ "=" + "'" + name + "'", null, null, null, null, null);
		if (mCursor != null)
			mCursor.moveToFirst();
		return mCursor;
	} 

	// ���ڵ� ����
	public boolean updateLogic(String name, String completeness, String state) {
		ContentValues args = new ContentValues();
		// args.put(KEY_NAME, name);
		args.put(KEY_COMPLETENESS, completeness);
		// args.put(KEY_VALUE, value);
		args.put(KEY_STATE, state);

		return mDb.update(DATABASE_TABLE, args, KEY_NAME + "=" + "'" + name
				+ "'", null) > 0;
	}

	public byte[][] getValue(String name) {

		String stringTemp = fetchLogic(name).getString(FIND_BY_VALUE);

		int count = (int) Math.sqrt(stringTemp.length() + 1);
		byte[][] valueArray = new byte[count][count];

		for (int i = 0; i < count; i++)
			for (int j = 0; j < count; j++)
				valueArray[j][i] = (byte) (stringTemp.charAt(i * count
						+ j) - 48);

		return valueArray;

	}

	public String getStringValue(String name) {

		String stringTemp = fetchLogic(name).getString(FIND_BY_VALUE);

		return stringTemp;

	}
	
	public Bitmap getBitmap(String name) {

		String stringTemp = fetchLogic(name).getString(FIND_BY_VALUE);
		int count = (int) Math.sqrt(stringTemp.length() + 1);

		byte[][] valueArray = new byte[count][count];

		for (int i = 0; i < count; i++)
			for (int j = 0; j < count; j++)
				valueArray[j][i] = (byte) (stringTemp.charAt(i * count
						+ j) - 48);

		Bitmap preViewImage;
		preViewImage = Bitmap.createBitmap(count, count,
				Bitmap.Config.ARGB_8888);

		for (int i = 0; i < count; i++)
			for (int j = 0; j < count; j++) {
				if (valueArray[i][j] == 1)
					preViewImage.setPixel(j, i, 0xffffffff);
				else
					preViewImage.setPixel(j, i, 0xff000000);

			}
		return preViewImage;
	}

	public long getTime(String name) {
		long time = fetchLogic(name).getLong(FIND_BY_TIME);
		return time;
	}

	public boolean setTime(String name, long time) {
		ContentValues newValues = new ContentValues();
		newValues.put(KEY_TIME, time);
		return mDb.update(DATABASE_TABLE, newValues, KEY_NAME + "=" + "'"
				+ name + "'", null) > 0;
	}

	public boolean setCompleteness(String name, Point pt, int value) {

		int[][] comTemp = getCompleteness(name);
		comTemp[pt.x][pt.y] = value;
		String comString = "";
		StringBuilder sb = new StringBuilder(comString);
		for (int i = 0; i < comTemp.length; i++)
			for (int j = 0; j < comTemp.length; j++) {
				sb.append(comTemp[i][j]);
				if ((i != comTemp.length - 1) || (j != comTemp.length - 1))
					sb.append(",");
			}
		comString = sb.toString();
		Log.e("com", comString);

		ContentValues newValues = new ContentValues();
		newValues.put(KEY_COMPLETENESS, comString);
		return mDb.update(DATABASE_TABLE, newValues, KEY_NAME + "=" + "'"
				+ name + "'", null) > 0;
	}

	public int[][] getCompleteness(String name) {

		String completeness = fetchLogic(name).getString(FIND_BY_COMPLETENESS);
		StringTokenizer st = new StringTokenizer(completeness, ",");
		int count = (int) Math.sqrt(st.countTokens());
		int[][] completenessArray = new int[count][count];
		for (int i = 0; i < count; i++)
			for (int j = 0; j < count; j++)
				completenessArray[i][j] = Integer.parseInt(st.nextToken());

		return completenessArray;
	}

	public int maxValue(int a, int b) {
		int c;
		if (a > b)
			c = a;
		else
			c = b;

		return c;
	}

	public int minValue(int a, int b) {
		int c;
		if (a > b)
			c = b;
		else
			c = a;

		return c;
	}

	public boolean setState(String name, Point start, Point end, byte[] value) {
		String state = fetchLogic(name).getString(FIND_BY_STATE);
		StringBuilder sb = new StringBuilder(state);
		int level = (int) Math.sqrt(state.length());
		ContentValues newValues = new ContentValues();

		if (start.y == end.y)
			for (int j = 0; j < value.length; j++)
				sb.setCharAt(start.y * level + minValue(start.x, end.x) + j,
						(char) (value[j] + 48));
		else {
			for (int j = 0; j < value.length; j++)
				sb.setCharAt((minValue(start.y, end.y) + j) * level + start.x,
						(char) (value[j] + 48));
		}

		String stateTemp = sb.toString();

		Log.e("length", Integer.toString(stateTemp.length()));

		newValues.put(KEY_STATE, stateTemp);
		return mDb.update(DATABASE_TABLE, newValues, KEY_NAME + "=" + "'"
				+ name + "'", null) > 0;
	}

	public byte[][] getState(String name) {

		String stringTemp = fetchLogic(name).getString(FIND_BY_STATE);
		byte[][] stateArray = stringToArray(stringTemp);

		return stateArray;
	}

	public String[] getNameList() {
		int count;
		Cursor cursorNow = fetchAllLogic();
		count = fetchAllLogic().getCount();
		String[] nameList = new String[count];
		cursorNow.moveToFirst();
		for (int i = 0; i < count; i++) {
			nameList[i] = cursorNow.getString(FIND_BY_NAME);
			cursorNow.moveToNext();
		}

		return nameList;
	}

	public int[] getCompletenessList() {
		int count;
		Cursor cursorNow = fetchAllLogic();
		count = fetchAllLogic().getCount();
		int[] completenessAvrList = new int[count];
		cursorNow.moveToFirst();
		for (int i = 0; i < count; i++) {
			StringTokenizer st = new StringTokenizer(
					cursorNow.getString(FIND_BY_COMPLETENESS), ",");
			int sectionCount = st.countTokens();
			int sum = 0;
			for (int j = 0; j < sectionCount; j++) {
				sum += Integer.parseInt(st.nextToken());
			}
			completenessAvrList[i] = sum / sectionCount;
			cursorNow.moveToNext();
		}
		return completenessAvrList;
	}
	
	public int getSumCompletness(String name){
		
		StringTokenizer st = new StringTokenizer(
				fetchLogic(name).getString(FIND_BY_COMPLETENESS), ",");
		int count = st.countTokens();
		int sum = 0;
		for (int j = 0; j < count; j++) {
			sum += Integer.parseInt(st.nextToken());
		}
		return sum / count;
		
	}

	public boolean setZero(String name, Point point) {
		ContentValues newValues = new ContentValues();

		int[][] comTemp = getCompleteness(name);
		comTemp[point.x][point.y] = 0;
		String comString = "";
		StringBuilder sbCom = new StringBuilder(comString);
		for (int i = 0; i < comTemp.length; i++)
			for (int j = 0; j < comTemp.length; j++) {
				sbCom.append(comTemp[i][j]);
				if ((i != comTemp.length - 1) || (j != comTemp.length - 1))
					sbCom.append(",");
			}
		comString = sbCom.toString();

		String state = fetchLogic(name).getString(FIND_BY_STATE);
		int level = (int) Math.sqrt(state.length());
		StringBuilder sbState = new StringBuilder(state);
		Log.e("level", level + "");
		for (int j = 0; j < 25; j++)
			for (int i = 0; i < 25; i++)
				sbState.setCharAt(
						(25 * point.x + j) * level + point.y * 25 + i, '0');
		String newState = sbState.toString();
		newValues.put(KEY_COMPLETENESS, comString);
		newValues.put(KEY_STATE, newState);

		return mDb.update(DATABASE_TABLE, newValues, KEY_NAME + "=" + "'"
				+ name + "'", null) > 0;
	}

	public String arrayToString(byte[][] tempArray) {
		String tempString = "";
		StringBuilder sb = new StringBuilder(tempString);
		for (int i = 0; i < tempArray.length; i++)
			for (int j = 0; j < tempArray.length; j++)
				sb.append(tempArray[i][j]);
		tempString = sb.toString();

		return tempString;
	}

	public byte[][] stringToArray(String stringTemp) {

		int count = (int) Math.sqrt(stringTemp.length() + 1);
		byte[][] tempArray = new byte[count][count];

		for (int i = 0; i < count; i++)
			for (int j = 0; j < count; j++)
				tempArray[i][j] = (byte) (stringTemp
						.charAt(i * count + j) - 48);

		return tempArray;

	}

	public String reduceString(String stringOri) {
		String stringTemp = "";

		if (stringOri.length() == 2500)
			for (int i = 0; i < stringOri.length(); i += 10) {
				char charTemp = 0;
				for (int j = 0; j < 10; j++)
					charTemp += (char) ((stringOri.charAt(i + j) & 1) << (10 - j));
				stringTemp += charTemp;
			}

		else {
			int deleteLength = 0;
			if (stringOri.length() == 10000)
				deleteLength = 4;
			if (stringOri.length() == 22500)
				deleteLength = 2;
			for (int i = 0; i < stringOri.length() - deleteLength; i += 7) {
				char charTemp = 0;
				for (int j = 0; j < 7; j++)
					charTemp += (char) ((stringOri.charAt(i + j) & 1) << (6 - j));

				if (charTemp >= 0 && charTemp <= 31)
					charTemp |= 0x0020;

				if (charTemp == 127)
					charTemp &= 0x7e;

				if (charTemp >= '/' && charTemp <= '9')
					charTemp |= 0x0040;

				if (stringTemp.length() != 0) {
					if (charTemp == stringTemp.charAt(stringTemp.length() - 1)) {
						stringTemp += '1';
						continue;
					}
					int numTemp = 0;
					int numLength = 0;
					while (true) {
						if (stringTemp.charAt(stringTemp.length() - 1
								- numLength) >= '0'
								&& stringTemp.charAt(stringTemp.length()
										- 1 - numLength) <= '9') {
							numTemp += (stringTemp.charAt(stringTemp
									.length() - 1 - numLength) - 48)
									* Math.pow(10, numLength);
							numLength++;
						} else
							break;
					}

					boolean duplication = false;
					if (numLength != 0)
						if (charTemp == stringTemp.charAt(stringTemp.length()
								- (numLength + 1))) {
							StringBuilder temp = new StringBuilder(stringTemp);
							temp.delete(stringTemp.length() - numLength,
									stringTemp.length());
							temp.append(numTemp + 1);
							stringTemp = temp.toString();
							duplication = true;
						}
					if (!duplication)
						stringTemp += charTemp;
				} else
					stringTemp += charTemp;

			}
		}
		return stringTemp;
	}

	public String stretchString(String stringOri) {
		String stringTemp = "";
		if (stringOri.length() == 250)
			for (int i = 0; i < stringOri.length(); i++) {
				for (int j = 0; j < 10; j++)
					stringTemp += ((stringOri.charAt(i) >> (10 - j)) & 1);
			}
		else
			for (int i = 0; i < stringOri.length(); i++) {
				char charTemp = stringOri.charAt(i);
				int numLength = 0;
				int numTemp = 0;
				while (true) {
					if ((i + numLength) >= stringOri.length())
						break;
					char chageCharTemp = stringOri.charAt(i + numLength);

					if (charTemp == 32) {
						charTemp = 0x0000;
						StringBuilder temp = new StringBuilder(stringOri);
						temp.setCharAt(i, charTemp);
						stringOri = temp.toString();
					}

					if (charTemp == 126) {
						charTemp = 0x007f;
						StringBuilder temp = new StringBuilder(stringOri);
						temp.setCharAt(i, charTemp);
						stringOri = temp.toString();
					}

					if (chageCharTemp >= '0'
							&& chageCharTemp <= '9') {
						numTemp *= 10;
						numTemp += (stringOri.charAt(i + numLength) - 48);
						numLength++;
					} else
						break;
				}

				if (numLength != 0) {
					for (int count = 0; count < numTemp; count++)
						for (int j = 0; j < 7; j++)
							stringTemp += ((stringOri.charAt(i - 1) >> (6 - j)) & 1);
					i += (numLength - 1);
				} else
					for (int j = 0; j < 7; j++)
						stringTemp += ((charTemp >> (6 - j)) & 1);
			}
		if (stringTemp.length() == 22498)
			for (int i = 0; i < 2; i++)
				stringTemp += stringTemp.charAt(stringTemp.length() - 1);
		if (stringTemp.length() == 9996)
			for (int i = 0; i < 4; i++)
				stringTemp += stringTemp.charAt(stringTemp.length() - 1);
		return stringTemp;
	}
	public long setItem(){
		ContentValues itemValues = new ContentValues();
		itemValues.put(KEY_COIN, 0);
		itemValues.put(KEY_HORIZON, 0);
		itemValues.put(KEY_VERTICAL, 0);
		itemValues.put(KEY_SQUAR, 0);
		itemValues.put(KEY_SHOW, 0);
		itemValues.put(KEY_REMOVEX, 0);
		return mDb.insert(DATABASE_TABLE2, null, itemValues);
		
	}
	
	public int getTableCount(){
			Cursor mCursor =  mDb.query(DATABASE_TABLE2, new String[] { KEY_COIN,
					KEY_HORIZON, KEY_VERTICAL, KEY_SQUAR, KEY_SHOW, KEY_REMOVEX }, null, null,
					null, null, null);
			return mCursor.getCount();
	}
	public Cursor fetchItem() {
		Cursor mCursor =  mDb.query(DATABASE_TABLE2, new String[] { KEY_COIN,
				KEY_HORIZON, KEY_VERTICAL, KEY_SQUAR, KEY_SHOW, KEY_REMOVEX }, null, null,
				null, null, null);
		if (mCursor != null)
			mCursor.moveToFirst();
		return mCursor;
	}
	
	public int getCoin(){
		int coin = fetchItem().getInt(FIND_BY_COIN);
		return coin;
	}
	
	public boolean setCoin(int newCoin){
		ContentValues newValues = new ContentValues();
		newValues.put(KEY_COIN, newCoin);
		return mDb.update(DATABASE_TABLE2, newValues, null
				, null) > 0;
	}
	
	public int getHorizon(){
		int horizon = fetchItem().getInt(FIND_BY_HORIZON);
		return horizon;
	}

	public boolean setHorizon(int newHorizon){
		ContentValues newValues = new ContentValues();
		newValues.put(KEY_HORIZON, newHorizon);
		return mDb.update(DATABASE_TABLE2, newValues, null
				, null) > 0;
	}
	
	public int getVertical(){
		int vertical = fetchItem().getInt(FIND_BY_VERTICAL);
		return vertical;
	}

	public boolean setVertical(int newVertical){
		ContentValues newValues = new ContentValues();
		newValues.put(KEY_VERTICAL, newVertical);
		return mDb.update(DATABASE_TABLE2, newValues, null
				, null) > 0;
	}
	
	public int getSquar(){
		int squar = fetchItem().getInt(FIND_BY_SQUAR);
		return squar;
	}

	public boolean setSquar(int newSquar){
		ContentValues newValues = new ContentValues();
		newValues.put(KEY_SQUAR, newSquar);
		return mDb.update(DATABASE_TABLE2, newValues, null
				, null) > 0;
	}
	
	public int getShow(){
		int show = fetchItem().getInt(FIND_BY_SHOW);
		return show;
	}

	public boolean setShow(int newShow){
		ContentValues newValues = new ContentValues();
		newValues.put(KEY_SHOW, newShow);
		return mDb.update(DATABASE_TABLE2, newValues, null
				, null) > 0;
	}
	public int getRemoveX(){
		int removeX = fetchItem().getInt(FIND_BY_REMOVEX);
		return removeX;
	}

	public boolean setRemoveX(int newItem){
		ContentValues newValues = new ContentValues();
		newValues.put(KEY_REMOVEX, newItem);
		return mDb.update(DATABASE_TABLE2, newValues, null
				, null) > 0;
	}


}
